package com.zoe.onelink.feign.listener;

import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2022</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2022-08-08
 */
@Slf4j
@RequiredArgsConstructor
public class NacosInstancesChangeNotifier extends Subscriber<InstancesChangeEvent> implements SmartInitializingSingleton {

    private final SpringClientFactory springClientFactory;
    private final String applicationName;

    @Override
    public void onEvent(InstancesChangeEvent event) {
        String nacosServiceName = event.getServiceName();
        String serviceName, serviceGroup;
        // 解析服务名与组名
        if (nacosServiceName.contains("@@")) {
            String[] serviceNameSplit = nacosServiceName.split("@@");
            serviceGroup = serviceNameSplit[0];
            serviceName = serviceNameSplit[1];
        } else {
            serviceGroup = event.getGroupName();
            serviceName = event.getServiceName();
        }
        ILoadBalancer loadBalancer = this.springClientFactory.getLoadBalancer(serviceName);
        if (this.applicationName.equals(serviceName)) {
            return;
        }
        String ips = event.getHosts().stream()
                .map(instance -> instance.getIp() + ":" + instance.getPort())
                .reduce((s1, s2) -> s1 + "," + s2)
                .orElse("");
        boolean couldUpdate = loadBalancer instanceof DynamicServerListLoadBalancer;
        log.info("[实例列表缓存清理] [清理结果:{}] 更新服务[{}@{}]持有的实例列表:[{}]", couldUpdate, serviceName, serviceGroup, ips);
        if (!couldUpdate) {
            return;
        }
        ((DynamicServerListLoadBalancer<?>) loadBalancer).updateListOfServers();
    }

    @Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }

    @Override
    public boolean scopeMatches(InstancesChangeEvent event) {
        // nacos-client 2.0.4 升级到 2.1.1 订阅逻辑有所调整 参考issue: #8433
        // 默认对所有事件生效
        return true;
    }

    @Override
    public void afterSingletonsInstantiated() {
        NotifyCenter.registerSubscriber(this);
    }
}
